home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / MSJV7_2B.ARJ / OBJ.C < prev    next >
C/C++ Source or Header  |  1992-03-01  |  30KB  |  1,104 lines

  1. /*
  2.   OLE SERVER DEMO           
  3.   Obj.c             
  4.                                                                      
  5.   This file contains object methods and various object-related support 
  6.   functions.
  7.                                                                      
  8.   (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved   
  9. */                                                                     
  10.  
  11. /* 
  12.    Important Note:
  13.  
  14.    No method should ever dispatch a DDE message or allow a DDE message to
  15.    be dispatched.
  16.    Therefore, no method should ever enter a message dispatch loop.
  17.    Also, a method should not show a dialog or message box, because the 
  18.    processing of the dialog box messages will allow DDE messages to be
  19.    dispatched.
  20. */
  21.  
  22.  
  23. #define SERVERONLY
  24. #include "Windows.h"
  25. #include "Ole.h"
  26. #include "SrvrDemo.h"
  27.  
  28.  
  29.  
  30. // Static functions.
  31. static HBITMAP GetBitmap (LPOBJ lpobj);
  32. static HANDLE  GetLink (LPOBJ lpobj);
  33. static HANDLE  GetMetafilePict (LPOBJ lpobj);
  34. static HANDLE  GetNative (LPOBJ lpobj);
  35. static int     GetObjNum (LPOBJ lpobj);
  36. static HANDLE  GetText (LPOBJ lpobj);
  37. static void    DrawObj (HDC hdc, LPOBJ lpobj, RECT rc, int dctype);
  38.  
  39.  
  40.  
  41. /* CreateNewObj
  42.  * ------------
  43.  *
  44.  * BOOL fDoc_Changed - The new value for the global variable fDocChanged.
  45.  *                     When initializing a new document, we need to create 
  46.  *                     a new object without the creation counting as a 
  47.  *                     change to the document.
  48.  *
  49.  * RETURNS: A pointer to the new object
  50.  *
  51.  * 
  52.  * CUSTOMIZATION: Re-implement
  53.  *                Some applications (like Server Demo) have a finite number of
  54.  *                fixed, distinct, non-overlapping objects.  Other applications
  55.  *                allow the user to create an object from any section of the
  56.  *                document.  For example, the user might select a portion of
  57.  *                a bitmap from a paint program, or a few lines of text from
  58.  *                a word processor.  This latter type of application probably
  59.  *                will not have a function like CreateNewObj.
  60.  *
  61.  */
  62. LPOBJ CreateNewObj (BOOL fDoc_Changed)
  63. {
  64.     HANDLE hObj = NULL;
  65.     LPOBJ  lpobj = NULL;
  66.     // index into an array of flags indicating if that object number is used.
  67.     int    ifObj = 0;    
  68.  
  69.     if ((hObj = LocalAlloc (LMEM_MOVEABLE|LMEM_ZEROINIT, sizeof (OBJ))) == NULL)
  70.       return NULL;
  71.  
  72.     if ((lpobj = (LPOBJ) LocalLock (hObj)) == NULL)
  73.     {
  74.       LocalFree (hObj);
  75.       return NULL;
  76.     }
  77.  
  78.     // Fill the fields in the object structure.
  79.     
  80.     // Find an unused number.
  81.     for (ifObj=1; ifObj <= cfObjNums; ifObj++)
  82.     {
  83.       if (docMain.rgfObjNums[ifObj]==FALSE)
  84.       {
  85.          docMain.rgfObjNums[ifObj]=TRUE;
  86.          break;
  87.       }
  88.     }
  89.  
  90.     if (ifObj==cfObjNums+1)
  91.     {
  92.       // Cannot create any more objects.
  93.       MessageBeep(0);
  94.       return NULL;
  95.     }
  96.  
  97.     wsprintf (lpobj->native.szName, "Object %d", ifObj);
  98.  
  99.     lpobj->aName            = GlobalAddAtom (lpobj->native.szName);
  100.     lpobj->hObj             = hObj;
  101.     lpobj->oleobject.lpvtbl = &objvtbl;
  102.     lpobj->native.idmColor  = IDM_RED;    // Default color 
  103.     lpobj->native.version   = version;
  104.     lpobj->native.nWidth    = OBJECT_WIDTH;          // Default size
  105.     lpobj->native.nHeight   = OBJECT_HEIGHT;
  106.     SetHiMetricFields (lpobj);
  107.  
  108.     // Place object in a location corrsponding to its number, for aesthetics.
  109.     lpobj->native.nX = (ifObj - 1) * 20;
  110.     lpobj->native.nY = (ifObj - 1) * 20;
  111.  
  112.     if (!CreateWindow (
  113.         "ObjClass",
  114.         "Obj",
  115.         WS_BORDER | WS_THICKFRAME | WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
  116.         lpobj->native.nX,
  117.         lpobj->native.nY,
  118.         lpobj->native.nWidth,
  119.         lpobj->native.nHeight,
  120.         hwndMain,
  121.         NULL,
  122.         hInst,
  123.         (LPSTR) lpobj ))
  124.          return FALSE;
  125.  
  126.     fDocChanged = fDoc_Changed;
  127.  
  128.     return lpobj;
  129. }
  130.  
  131.  
  132.  
  133. /* CutOrCopyObj
  134.  * ------------
  135.  *
  136.  * Put data onto clipboard in all the formats supported.  If the 
  137.  * fOpIsCopy is TRUE, the operation is COPY, otherwise it is CUT.
  138.  * This is important, because we cannot put the Object Link format
  139.  * onto the clipboard if the object was cut from the document (there is
  140.  * no longer anything to link to).
  141.  *
  142.  * BOOL fOpIsCopy - TRUE if the operation is COPY; FALSE if CUT
  143.  * 
  144.  * CUSTOMIZATION: None
  145.  *
  146.  *
  147.  */
  148. void CutOrCopyObj (BOOL fOpIsCopy)
  149. {
  150.     LPOBJ       lpobj;
  151.     HANDLE     hData;
  152.  
  153.     if (OpenClipboard (hwndMain))
  154.     {
  155.         EmptyClipboard ();
  156.  
  157.         lpobj = SelectedObject();
  158.  
  159.         if ((hData = GetNative (lpobj)) != NULL)
  160.             SetClipboardData(cfNative, hData);
  161.  
  162.         if ((hData = GetLink(lpobj)) != NULL)
  163.             SetClipboardData(cfOwnerLink, hData);
  164.  
  165.         if (fOpIsCopy && docMain.doctype == doctypeFromFile)
  166.         {
  167.             // Can create a link if object exists in a file.
  168.             if ((hData = GetLink(lpobj)) != NULL)
  169.                SetClipboardData(cfObjectLink, hData);
  170.         }
  171.  
  172.         if ((hData = GetMetafilePict(lpobj)) != NULL)
  173.         { 
  174.             SetClipboardData(CF_METAFILEPICT, hData);
  175. //            GlobalFree(hData);
  176.         }
  177.  
  178.         if ((hData = GetBitmap(lpobj)) != NULL)
  179.         { 
  180.             SetClipboardData(CF_BITMAP, hData);
  181. //            DeleteObject(hData);
  182.         }
  183.  
  184.  
  185.         CloseClipboard ();
  186.     }
  187. }
  188.  
  189.  
  190. /* DestroyObj
  191.  * ----------
  192.  *
  193.  * Revoke an object, and free all memory that had been allocated for it.
  194.  *
  195.  * HWND hwnd - The object's window
  196.  * 
  197.  * CUSTOMIZATION: Re-implement, making sure you free all the memory that
  198.  *                had been allocated for the OBJ structure and each of its
  199.  *                fields.
  200.  * 
  201.  */
  202. void DestroyObj (HWND hwnd)
  203. {
  204.    LPOBJ lpobj = HwndToLpobj (hwnd);
  205.  
  206.    if(lpobj->aName)
  207.    {
  208.       GlobalDeleteAtom (lpobj->aName);
  209.       lpobj->aName = NULL;
  210.    }
  211.  
  212.    if (lpobj->hpal) 
  213.       DeleteObject (lpobj->hpal);
  214.    // Allow the object's number to be reused.
  215.    docMain.rgfObjNums [GetObjNum(lpobj)] = FALSE;
  216.  
  217.  
  218.    // Free the memory that had been allocated for the object structure itself.
  219.    LocalUnlock (lpobj->hObj);
  220.    LocalFree (lpobj->hObj);
  221. }
  222.  
  223.  
  224.  
  225. /* DrawObj
  226.  * -------
  227.  *
  228.  * This function draws an object onto the screen, into a metafile, or into
  229.  * a bitmap.
  230.  * The object will always look the same.
  231.  *
  232.  * HDC    hdc    - The device context to render the object into
  233.  * LPOBJ  lpobj  - The object to render
  234.  * RECT   rc     - The rectangle bounds of the object
  235.  * DCTYPE dctype - The type of device context.
  236.  * 
  237.  * CUSTOMIZATION: Server Demo specific
  238.  *
  239.  */
  240. static void DrawObj (HDC hdc, LPOBJ lpobj, RECT rc, int dctype)
  241. {
  242.    HPEN     hpen;
  243.    HPEN     hpenOld;
  244.    HPALETTE hpalOld = NULL;
  245.  
  246.    if (dctype == dctypeMetafile)
  247.    {
  248.       SetWindowOrg (hdc, 0, 0);
  249.       // Paint entire object into the given rectangle.
  250.       SetWindowExt (hdc, rc.right, rc.bottom);
  251.    }
  252.  
  253.    if (lpobj->hpal)
  254.    {
  255.       hpalOld = SelectPalette (hdc, lpobj->hpal, TRUE);
  256.       RealizePalette (hdc);
  257.    }
  258.  
  259.    // Select brush of the color specified in the native data.
  260.    SelectObject (hdc, hbrColor [lpobj->native.idmColor - IDM_RED] );
  261.  
  262.    hpen = CreatePen (PS_SOLID, 
  263.                      /* Width */ (rc.bottom-rc.top) / 10,
  264.                      /* Gray */ 0x00808080);
  265.    hpenOld = SelectObject (hdc, hpen);
  266.  
  267.    // Draw rectangle with the gray pen and fill it in with the selected brush.
  268.    Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
  269.  
  270.    // Print name of object inside rectangle.
  271.    SetBkMode (hdc, TRANSPARENT);
  272.    SetTextAlign (hdc, TA_BASELINE | TA_CENTER);
  273.    TextOut (hdc, 
  274.             rc.right/2, 
  275.             (rc.top+rc.bottom)/2, 
  276.             lpobj->native.szName, 
  277.             lstrlen (lpobj->native.szName));
  278.  
  279.    // Restore original objects
  280.    SelectObject (hdc, 
  281.                  (dctype == dctypeMetafile) 
  282.                      ? GetStockObject (BLACK_PEN) : hpenOld);
  283.    if (hpalOld)
  284.    {
  285.       SelectPalette (hdc, 
  286.                      (dctype == dctypeMetafile) 
  287.                         ? GetStockObject (DEFAULT_PALETTE) : hpalOld,
  288.                      TRUE);
  289.    }
  290.  
  291.    DeleteObject (hpen);
  292. }
  293.  
  294.  
  295.  
  296. /* GetBitmap
  297.  * ---------
  298.  *
  299.  * Return a handle to an object's picture data in bitmap format.
  300.  *
  301.  * LPOBJ lpobj - The object
  302.  * 
  303.  * RETURNS: A handle to the object's picture data
  304.  * 
  305.  * CUSTOMIZATION: Re-implement
  306.  *
  307.  */
  308. static HBITMAP GetBitmap (LPOBJ lpobj)
  309. {
  310.     HDC         hdcObj;
  311.     HDC         hdcMem;
  312.     RECT        rc;
  313.     HBITMAP     hbitmap;
  314.     HBITMAP     hbitmapOld;
  315.  
  316.  
  317.     hdcObj = GetDC (lpobj->hwnd);
  318.     // Create a memory device context.
  319.     hdcMem = CreateCompatibleDC (hdcObj);
  320.     GetClientRect (lpobj->hwnd, (LPRECT)&rc);
  321.     // Create new bitmap object based on the bitmap of the OLE object.
  322.     hbitmap = CreateCompatibleBitmap 
  323.       (hdcObj, rc.right - rc.left, rc.bottom - rc.top);
  324.     // Select new bitmap as the bitmap object for the memory device context.
  325.     hbitmapOld = SelectObject (hdcMem, hbitmap);
  326.  
  327.     // Paint directly into the memory dc using the new bitmap object.
  328.     DrawObj (hdcMem, lpobj, rc, dctypeBitmap);
  329.  
  330.     // Restore old bitmap object.
  331.     hbitmap = SelectObject (hdcMem, hbitmapOld);
  332.     DeleteDC (hdcMem);
  333.     ReleaseDC (lpobj->hwnd, hdcObj);
  334.  
  335.     // convert width and height to HIMETRIC units
  336.     rc.right  = rc.right - rc.left;
  337.     rc.bottom = rc.bottom - rc.top;
  338.     DeviceToHiMetric (hwndMain, (LPPOINT) &rc.right);
  339.     
  340.     // Set the 1/10 of HIMETRIC units for the bitmap
  341.     SetBitmapDimension (hbitmap, (int) (rc.right/10), (int) (rc.bottom/10));
  342.         
  343.     return hbitmap;
  344. }
  345.  
  346.  
  347.  
  348. /* GetLink
  349.  * -------
  350.  *
  351.  * Return a handle to an object's object or owner link data.
  352.  * Link information is in the form of three zero-separated strings,
  353.  * terminated with two zero bytes:  CLASSNAME\0DOCNAME\0OBJNAME\0\0
  354.  *
  355.  * LPOBJ lpobj - The object 
  356.  * 
  357.  * RETURNS: A handle to the object's link data
  358.  * 
  359.  * CUSTOMIZATION: Re-implement
  360.  *
  361.  */
  362. static HANDLE GetLink (LPOBJ lpobj)
  363. {
  364.  
  365.     char   sz[cchFilenameMax];
  366.     LPSTR  lpszLink = NULL;
  367.     HANDLE hLink = NULL;
  368.     int    cchLen;
  369.     int    i;
  370.  
  371.     // First make the class name.
  372.     lstrcpy (sz, szClassName);
  373.     cchLen = lstrlen (sz) + 1;
  374.  
  375.     // Then the document name.
  376.     cchLen += GlobalGetAtomName 
  377.                (docMain.aName, (LPSTR)sz + cchLen, 
  378.                 cchFilenameMax - cchLen) + 1;
  379.  
  380.     // Then the object name.
  381.     lstrcpy (sz + cchLen, lpobj->native.szName);
  382.     cchLen += lstrlen (lpobj->native.szName) + 1;
  383.  
  384.     // Add a second null to the end.
  385.     sz[cchLen++] = 0;       
  386.  
  387.  
  388.     hLink = GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT, cchLen);
  389.     if (hLink == NULL)
  390.       return NULL;
  391.     if ((lpszLink = GlobalLock (hLink)) == NULL)
  392.     {
  393.       GlobalFree (hLink);
  394.       return NULL;
  395.     }
  396.  
  397.     for (i=0; i < cchLen; i++)
  398.         lpszLink[i] = sz[i];
  399.  
  400.     GlobalUnlock (hLink);
  401.  
  402.     return hLink;
  403. }
  404.  
  405.  
  406.  
  407. /* GetMetafilePict
  408.  * ---------------
  409.  *
  410.  * Return a handle to an object's picture data in metafile format.
  411.  *
  412.  * LPOBJ lpobj - The object
  413.  * 
  414.  * RETURNS: A handle to the object's data in metafile format.
  415.  *
  416.  * CUSTOMIZATION: Re-implement
  417.  *
  418.  */
  419. static HANDLE GetMetafilePict (LPOBJ lpobj)
  420. {
  421.  
  422.     LPMETAFILEPICT  lppict = NULL;
  423.     HANDLE          hpict = NULL;
  424.     HANDLE          hMF = NULL;
  425.     RECT            rc;
  426.     HDC             hdc;
  427.  
  428.     hdc = CreateMetaFile(NULL);
  429.  
  430.     GetClientRect (lpobj->hwnd, (LPRECT)&rc);
  431.  
  432.     // Paint directly into the metafile.
  433.     DrawObj (hdc, lpobj, rc, dctypeMetafile);
  434.  
  435.     // Get handle to the metafile.
  436.     if ((hMF = CloseMetaFile (hdc)) == NULL)
  437.       return NULL;
  438.  
  439.     if(!(hpict = GlobalAlloc (GMEM_DDESHARE, sizeof (METAFILEPICT))))
  440.     {
  441.         DeleteMetaFile (hMF);
  442.         return NULL;
  443.     }
  444.  
  445.     if ((lppict = (LPMETAFILEPICT)GlobalLock (hpict)) == NULL)
  446.     {
  447.         DeleteMetaFile (hMF);
  448.         GlobalFree (hpict);
  449.         return NULL;
  450.     }
  451.  
  452.     rc.right  = rc.right - rc.left;
  453.     rc.bottom = rc.bottom - rc.top;
  454.     
  455.     DeviceToHiMetric (hwndMain, (LPPOINT) &rc.right);
  456.  
  457.     lppict->mm   =  MM_ANISOTROPIC;
  458.     lppict->hMF  =  hMF;
  459.     lppict->xExt =  rc.right;
  460.     lppict->yExt =  rc.bottom;
  461.     GlobalUnlock (hpict);
  462.     return hpict;
  463. }
  464.  
  465.  
  466.  
  467. /* GetNative
  468.  * ---------
  469.  *
  470.  * Return a handle to an object's native data.
  471.  *
  472.  * LPOBJ lpobj - The object whose native data is to be retrieved.
  473.  * 
  474.  * RETURNS: a handle to the object's native data.
  475.  *
  476.  * CUSTOMIZATION: The line "*lpnative = lpobj->native;" will change to 
  477.  *                whatever code is necessary to copy an object's native data.
  478.  *
  479.  */
  480. static HANDLE GetNative (LPOBJ lpobj)
  481. {
  482.    LPNATIVE lpnative = NULL;
  483.    HANDLE   hNative  = NULL;
  484.  
  485.    hNative = GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT, sizeof (NATIVE));
  486.    if (hNative == NULL)
  487.       return NULL;
  488.    if ((lpnative = (LPNATIVE) GlobalLock (hNative)) == NULL)
  489.    {
  490.       GlobalFree (hNative);
  491.       return NULL;
  492.    }
  493.  
  494.    // Copy the native data.
  495.    *lpnative = lpobj->native;
  496.  
  497.    GlobalUnlock (hNative);
  498.    return hNative;
  499. }
  500.  
  501.  
  502.  
  503. /* GetObjNum
  504.  * ---------
  505.  *
  506.  * LPSTR lpobj - The object whose number is desired
  507.  *
  508.  * RETURNS: The number of the object, i.e., the numerical portion of its name.
  509.  *
  510.  * CUSTOMIZATION: Server Demo specific
  511.  */
  512. static int GetObjNum (LPOBJ lpobj)
  513. {
  514.    LPSTR lpsz;
  515.    int n=0;
  516.  
  517.    lpsz = lpobj->native.szName + 7;
  518.    while (*lpsz && *lpsz>='0' && *lpsz<='9')
  519.       n = 10*n + *lpsz++ - '0';
  520.    return n;
  521. }
  522.  
  523.  
  524.  
  525. /* GetText
  526.  * -------
  527.  *
  528.  * Return a handle to an object's data in text form.
  529.  * This function simply returns the name of the object.
  530.  *
  531.  * LPOBJ lpobj - The object
  532.  * 
  533.  * RETURNS: A handle to the object's text.
  534.  *
  535.  * CUSTOMIZATION: Re-implement, if your application supports CF_TEXT as a 
  536.  *                presentation format.
  537.  *
  538.  */
  539. static HANDLE GetText (LPOBJ lpobj)
  540. {
  541.     HANDLE hText    = NULL;
  542.     LPSTR  lpszText = NULL;
  543.  
  544.     if(!(hText = GlobalAlloc (GMEM_DDESHARE, sizeof (lpobj->native.szName))))
  545.       return NULL;
  546.  
  547.     if (!(lpszText = GlobalLock (hText)))
  548.       return NULL;
  549.  
  550.     lstrcpy (lpszText, lpobj->native.szName);
  551.  
  552.     GlobalUnlock (hText);
  553.  
  554.     return hText;
  555. }
  556.  
  557.  
  558.  
  559. /* ObjDoVerb                OBJECT "DoVerb" METHOD
  560.  * ---------
  561.  *
  562.  * This method is called by the client, through the library, to either
  563.  * PLAY, or EDIT the object.  PLAY is implemented as a beep, and
  564.  * EDIT will bring up the server and show the object for editing.
  565.  *
  566.  * LPOLEOBJECT lpoleobject - The OLE object
  567.  * WORD wVerb              - The verb acting on the object: PLAY or EDIT
  568.  * BOOL fShow              - Should the object be shown?
  569.  * BOOL fTakeFocus         - Should the object window get the focus?
  570.  * 
  571.  * RETURNS:        OLE_OK
  572.  *
  573.  * CUSTOMIZATION: Add any more verbs your application supports.
  574.  *                Implement verbPlay if your application supports it.
  575.  *
  576.  */
  577. OLESTATUS FAR PASCAL ObjDoVerb 
  578.    (LPOLEOBJECT lpoleobject, WORD wVerb, BOOL fShow, BOOL fTakeFocus)
  579. {
  580.     switch (wVerb) 
  581.     {
  582.          case verbPlay:
  583.          {  // The application can do whatever is appropriate for the object.
  584.             int i;
  585.             for (i=0; i<25;i++) MessageBeep (0);
  586.             return OLE_OK;
  587.          }
  588.  
  589.          case verbEdit:
  590.             if (fShow)
  591.                return objvtbl.Show (lpoleobject, fTakeFocus);
  592.             else
  593.                return OLE_OK;
  594.          default:
  595.             // Unknown verb.
  596.             return OLE_ERROR_DOVERB;
  597.     }
  598. }
  599.  
  600.  
  601.  
  602. /* ObjEnumFormats        OBJECT "EnumFormats" METHOD
  603.  * ---------------
  604.  *
  605.  * This method is used to enumerate all supported clipboard formats.
  606.  * Terminate by returning NULL.
  607.  *
  608.  * LPOLEOBJECT lpoleobject - The OLE object
  609.  * OLECLIPFORMAT cfFormat  - The 'current' clipboard format
  610.  * 
  611.  * RETURNS: The 'next' clipboard format which is supported.
  612.  *
  613.  * CUSTOMIZATION: Verify that the list of formats this function 
  614.  *                returns matches the list of formats your application 
  615.  *                supports.
  616.  *
  617.  */
  618. OLECLIPFORMAT FAR PASCAL ObjEnumFormats
  619.    (LPOLEOBJECT lpoleobject, OLECLIPFORMAT cfFormat)
  620. {
  621.       if (cfFormat == 0)
  622.         return cfNative;
  623.  
  624.       if (cfFormat == cfNative)
  625.          return cfOwnerLink;
  626.  
  627.       if (cfFormat == cfOwnerLink)
  628.          return CF_METAFILEPICT;
  629.  
  630.       if (cfFormat == CF_METAFILEPICT)
  631.          return CF_BITMAP;
  632.  
  633.       if (cfFormat == CF_BITMAP)
  634.          return cfObjectLink;
  635.  
  636.       if (cfFormat == cfObjectLink)
  637.          return NULL;
  638.  
  639.       return NULL;
  640. }
  641.  
  642.  
  643.  
  644. /* ObjGetData                OBJECT "GetData" METHOD
  645.  * -----------
  646.  *
  647.  * Return the data requested for the specified object in the specified format.
  648.  *
  649.  * LPOLEOBJECT lpoleobject - The OLE object
  650.  * WORD cfFormat           - The data type requested in standard
  651.  *                           clipboard format
  652.  * LPHANDLE lphandle       - Pointer to handle to memory where data
  653.  *                           will be stored
  654.  * 
  655.  * RETURNS: OLE_OK           if successful
  656.  *          OLE_ERROR_MEMORY if there was an error getting the data.
  657.  *          OLE_ERROR_FORMAT if the requested format is unknown.
  658.  *
  659.  * 
  660.  * CUSTOMIZATION: Add any additional formats your application supports, and
  661.  *                remove any formats it does not support.
  662.  *
  663.  */
  664. OLESTATUS FAR PASCAL ObjGetData
  665.    (LPOLEOBJECT lpoleobject, WORD cfFormat, LPHANDLE lphandle)
  666. {
  667.  
  668.    LPOBJ lpobj;
  669.  
  670.    lpobj = (LPOBJ) lpoleobject;
  671.  
  672.    if (cfFormat ==  cfNative)
  673.    {
  674.       if (!(*lphandle = GetNative (lpobj)))
  675.          return OLE_ERROR_MEMORY;
  676.       // The client has requested the data in native format, therefore
  677.       // the data in the client and server are in sync.
  678.       fDocChanged = FALSE;
  679.       return OLE_OK; 
  680.    }                
  681.  
  682.    if (cfFormat == CF_METAFILEPICT)
  683.    {
  684.       if (!(*lphandle = GetMetafilePict (lpobj)))
  685.          return OLE_ERROR_MEMORY;
  686.       return OLE_OK; 
  687.    }
  688.  
  689.    if (cfFormat == CF_BITMAP)
  690.    {
  691.       if (!(*lphandle = (HANDLE)GetBitmap (lpobj)))
  692.          return OLE_ERROR_MEMORY;
  693.       return OLE_OK; 
  694.    }
  695.  
  696.    if (cfFormat == CF_TEXT) 
  697.    {
  698.       if (!(*lphandle = GetText (lpobj)))
  699.          return OLE_ERROR_MEMORY;
  700.       return OLE_OK; 
  701.    }
  702.  
  703.    if (cfFormat == cfObjectLink)
  704.    {
  705.       if (!(*lphandle = GetLink (lpobj)))
  706.          return OLE_ERROR_MEMORY;
  707.       return OLE_OK; 
  708.    }
  709.  
  710.    if (cfFormat ==  cfOwnerLink)
  711.    {
  712.       if (!(*lphandle = GetLink (lpobj)))
  713.          return OLE_ERROR_MEMORY;
  714.       return OLE_OK; 
  715.    }
  716.  
  717.    return OLE_ERROR_FORMAT;
  718. }
  719.  
  720.  
  721.  
  722. /* ObjQueryProtocol                OBJECT "QueryProtocol" METHOD
  723.  * ----------------
  724.  *
  725.  * LPOLEOBJECT lpoleobject - The OLE object
  726.  * LPSTR lpszProtocol      - The protocol name, either "StdFileEditing"
  727.  *                           or "StdExecute"
  728.  * 
  729.  * RETURNS: If lpszProtocol is supported, return a pointer to an OLEOBJECT 
  730.  *          structure with an appropriate method table for that protocol.
  731.  *          Otherwise, return NULL.
  732.  *
  733.  * CUSTOMIZATION: Allow any additional protocols your application supports.
  734.  *
  735.  *
  736.  */
  737. LPVOID FAR PASCAL ObjQueryProtocol 
  738.    (LPOLEOBJECT lpoleobject, LPSTR lpszProtocol)
  739. {
  740.    return lstrcmp (lpszProtocol, "StdFileEditing") ? NULL : lpoleobject ;
  741. }
  742.  
  743.  
  744.  
  745. /* ObjRelease                OBJECT "Release" METHOD
  746.  * -----------
  747.  *
  748.  * The server application should not destroy data when the library calls the 
  749.  * ReleaseObj method.
  750.  * The library calls the ReleaseObj method when no clients are connected 
  751.  * to the object.
  752.  *
  753.  * LPOLEOBJECT lpoleobject - The OLE object
  754.  * 
  755.  * RETURNS: OLE_OK
  756.  * 
  757.  * CUSTOMIZATION: Re-implement.  Do whatever needs to be done, if anything,
  758.  *                when no clients are connected to an object.
  759.  *
  760.  */
  761. OLESTATUS FAR PASCAL ObjRelease (LPOLEOBJECT lpoleobject)
  762. {
  763.    int i;
  764.    /* No client is connected to the object so break all assocaiations
  765.       between clients and the object. */
  766.    for (i=0; i < clpoleclient; i++)
  767.       ((LPOBJ)lpoleobject)->lpoleclient[i] = NULL;
  768.    return OLE_OK;
  769. }
  770.  
  771.  
  772.  
  773. /* ObjSetBounds        OBJECT "SetBounds" METHOD
  774.  * ------------
  775.  *
  776.  * This method is called to set new bounds for an object.
  777.  * The bounds are in HIMETRIC units.
  778.  * A call to this method is ignored for linked objects because the size of
  779.  * a linked object depends only on the source file.
  780.  *
  781.  * LPOLEOBJECT lpoleobject - The OLE object
  782.  * LPRECT lprect           - The new bounds
  783.  * 
  784.  * RETURNS: OLE_OK
  785.  *
  786.  * CUSTOMIZATION: Re-implement
  787.  *                How an object is sized is application-specific. (Server Demo
  788.  *                uses MoveWindow.)
  789.  *
  790.  */
  791. OLESTATUS FAR PASCAL ObjSetBounds (LPOLEOBJECT lpoleobj, LPRECT lprect)
  792. {
  793.    if (docMain.doctype == doctypeEmbedded)
  794.    {
  795.       RECT rect = *lprect;
  796.       LPOBJ lpobj = (LPOBJ) lpoleobj;
  797.       
  798.       // the units are in HIMETRIC
  799.       rect.right   = rect.right - rect.left;
  800.       rect.bottom  = rect.top - rect.bottom;
  801.       HiMetricToDevice (hwndMain, (LPPOINT) &rect.right);
  802.       MoveWindow (lpobj->hwnd, lpobj->native.nX, lpobj->native.nY, 
  803.                   rect.right + 2 * GetSystemMetrics(SM_CXFRAME), 
  804.                   rect.bottom + 2 * GetSystemMetrics(SM_CYFRAME), 
  805.                   TRUE);
  806.    }
  807.    return OLE_OK;
  808. }
  809.  
  810.  
  811.  
  812. /* ObjSetColorScheme                OBJECT "SetColorScheme" METHOD
  813.  * -----------------
  814.  *
  815.  * The client calls this method to suggest a color scheme (palette) for
  816.  * the server to use for the object.
  817.  *
  818.  * LPOLEOBJECT  lpoleobject       - The OLE object
  819.  * LPLOGPALETTE lppal             - Suggested palette
  820.  *
  821.  * RETURNS: OLE_ERROR_PALETTE if CreatePalette fails, 
  822.  *          OLE_OK otherwise
  823.  *
  824.  * 
  825.  * CUSTOMIZATION: If your application supports color schemes, then this 
  826.  *                function is a good example of how to create and store
  827.  *                a palette.
  828.  *
  829.  */
  830. OLESTATUS FAR PASCAL ObjSetColorScheme 
  831.    (LPOLEOBJECT lpoleobject, LPLOGPALETTE lppal)
  832. {
  833.    HPALETTE hpal = CreatePalette (lppal);
  834.    LPOBJ lpobj   = (LPOBJ) lpoleobject;
  835.  
  836.    if (hpal==NULL)
  837.       return OLE_ERROR_PALETTE;
  838.  
  839.    if (lpobj->hpal) 
  840.       DeleteObject (lpobj->hpal);
  841.    lpobj->hpal = hpal;
  842.    return OLE_OK;
  843. }
  844.  
  845.  
  846.  
  847. /* ObjSetData                OBJECT "SetData" METHOD
  848.  * ----------
  849.  *
  850.  * This method is used to store data into the object in the specified
  851.  * format.  This will be called with Native format after an embedded
  852.  * object has been opened by the Edit method.
  853.  *
  854.  * LPOLEOBJECT lpoleobject      - The OLE object
  855.  * WORD cfFormat                - Data type, i.e., clipboard format
  856.  * HANDLE hdata                 - Handle to the data.
  857.  * 
  858.  * RETURNS:       OLE_OK if the data was stored properly
  859.  *                OLE_ERROR_FORMAT if format was not cfNative.
  860.  *                OLE_ERROR_MEMORY if memory could not be locked.
  861.  * 
  862.  * CUSTOMIZATION: The large then-clause will need to be re-implemented for
  863.  *                your application.  You may wish to support additional
  864.  *                formats besides cfNative.
  865.  *
  866.  */
  867. OLESTATUS FAR PASCAL ObjSetData 
  868.    (LPOLEOBJECT lpoleobject, OLECLIPFORMAT cfFormat, HANDLE hdata)
  869. {
  870.     LPNATIVE lpnative;
  871.     LPOBJ    lpobj;
  872.  
  873.     lpobj = (LPOBJ)lpoleobject;
  874.  
  875.     if (cfFormat != cfNative)
  876.     {
  877.       return OLE_ERROR_FORMAT;
  878.     }
  879.  
  880.     lpnative = (LPNATIVE) GlobalLock (hdata);
  881.  
  882.     if (lpnative)
  883.     {
  884.         lpobj->native = *lpnative;
  885.         if (lpobj->aName)
  886.             GlobalDeleteAtom (lpobj->aName);
  887.         lpobj->aName = GlobalAddAtom (lpnative->szName);
  888.         // CreateNewObj made an "Object 1" but we may be changing its number.
  889.         docMain.rgfObjNums[1] = FALSE;
  890.         docMain.rgfObjNums [GetObjNum(lpobj)] = TRUE;
  891.  
  892.         MoveWindow (lpobj->hwnd, 0, 0,
  893.                     lpobj->native.nWidth + 2 * GetSystemMetrics(SM_CXFRAME), 
  894.                     lpobj->native.nHeight+ 2 * GetSystemMetrics(SM_CYFRAME), 
  895.                     FALSE);
  896.         GlobalUnlock (hdata);
  897.     }
  898.     // Server is responsible for deleting the data.
  899.     GlobalFree(hdata);           
  900.     return lpnative ? OLE_OK : OLE_ERROR_MEMORY;
  901. }
  902.  
  903.  
  904.  
  905. /* ObjSetTargetDevice        OBJECT "SetTargetDevice" METHOD
  906.  * -------------------
  907.  *
  908.  * This method is used to indicate the device type that an object
  909.  * will be rendered on.  It is the server's responsibility to free hdata.
  910.  *
  911.  * LPOLEOBJECT lpoleobject - The OLE object
  912.  * HANDLE hdata            - Handle to memory containing
  913.  *                           a StdTargetDevice structure
  914.  * 
  915.  * RETURNS: OLE_OK
  916.  * 
  917.  * CUSTOMIZATION: Implement.  Server Demo currently does not do anything.
  918.  *
  919.  */
  920. OLESTATUS FAR PASCAL ObjSetTargetDevice (LPOLEOBJECT lpoleobject, HANDLE hdata)
  921. {
  922.     if (hdata == NULL)
  923.     {
  924.       // Rendering for the screen is requested.
  925.     }
  926.     else
  927.     {
  928.       LPSTR lpstd = (LPSTR) GlobalLock (hdata);
  929.       // lpstd points to a StdTargetDevice structure.
  930.       // Use it to do whatever is appropriate to generate the best results 
  931.       // on the specified target device.
  932.       GlobalUnlock (hdata);
  933.       // Server is responsible for freeing the data.
  934.       GlobalFree (hdata);  
  935.     }
  936.     return OLE_OK;
  937. }
  938.  
  939.  
  940.  
  941. /* ObjShow                OBJECT "Show" METHOD
  942.  * --------
  943.  *
  944.  * This method is used to display the object.  
  945.  * The server application should be activated and brought to the top.
  946.  * Also, in a REAL server application, the object should be scrolled
  947.  * into view.  The object should be selected.
  948.  *
  949.  * LPOLEOBJECT lpoleobject - Pointer to the OLE object
  950.  * BOOL fTakeFocus         - Should server window get the focus?
  951.  * 
  952.  * RETURNS:        OLE_OK
  953.  *
  954.  * 
  955.  * CUSTOMIZATION: In your application, the document should be scrolled 
  956.  *                to bring the object into view.  Server Demo brings the 
  957.  *                object to the front, in case it is a linked object inside a 
  958.  *                document with other objects obscuring it.
  959.  *
  960.  */
  961. OLESTATUS FAR PASCAL ObjShow (LPOLEOBJECT lpoleobject, BOOL fTakeFocus)
  962. {
  963.     LPOBJ lpobj;
  964.     HWND hwndOldFocus;
  965.  
  966.     hwndOldFocus = GetFocus();
  967.     lpobj = (LPOBJ) lpoleobject;
  968.  
  969.     ShowWindow(hwndMain, SW_SHOWNORMAL);
  970.  
  971.     BringWindowToTop (lpobj->hwnd);
  972.     SetFocus (fTakeFocus ? lpobj->hwnd : hwndOldFocus);
  973.     return OLE_OK;
  974. }
  975.  
  976.  
  977.  
  978. /* PaintObj
  979.  * ---------
  980.  *
  981.  * This function is called by the WM_PAINT message to paint an object 
  982.  * on the screen.  
  983.  *
  984.  * HWND hwnd - The object window in which to paint the object
  985.  *
  986.  * CUSTOMIZATION: Server Demo specific
  987.  *
  988.  */
  989. void PaintObj (HWND hwnd)
  990. {
  991.     LPOBJ       lpobj;
  992.     RECT        rc;
  993.     HDC         hdc;
  994.     PAINTSTRUCT paintstruct;
  995.  
  996.     BeginPaint (hwnd, &paintstruct);
  997.     hdc = GetDC (hwnd);
  998.  
  999.     lpobj = HwndToLpobj (hwnd);
  1000.     GetClientRect (hwnd, (LPRECT) &rc);
  1001.  
  1002.     DrawObj (hdc, lpobj, rc, dctypeScreen);
  1003.  
  1004.     ReleaseDC (hwnd, hdc);
  1005.     EndPaint (hwnd, &paintstruct);
  1006. }
  1007.  
  1008.  
  1009.  
  1010. /* RevokeObj
  1011.  * ---------
  1012.  *
  1013.  * Call OleRevokeObject because the user has destroyed the object.
  1014.  *
  1015.  * LPOBJ lpobj - The object which has been destroyed
  1016.  *
  1017.  * 
  1018.  * CUSTOMIZATION: You will only need to call OleRevokeObject once if there
  1019.  *                is only one LPOLECLIENT in your OBJ structure, which there
  1020.  *                should be.
  1021.  *
  1022.  */
  1023. void RevokeObj (LPOBJ lpobj)
  1024. {
  1025.    int i;
  1026.  
  1027.    for (i=0; i< clpoleclient; i++)
  1028.    {
  1029.       if (lpobj->lpoleclient[i])
  1030.          OleRevokeObject (lpobj->lpoleclient[i]);
  1031.       else 
  1032.          /* if lpobj->lpoleclient[i]==NULL then there are no more non-NULLs
  1033.             in the array. */
  1034.          break;
  1035.    }
  1036. }
  1037.  
  1038.  
  1039.  
  1040. /* SendObjMsg
  1041.  * ----------
  1042.  *
  1043.  * This function sends a message to a specific object.
  1044.  *
  1045.  * LPOBJ lpobj   - The object
  1046.  * WORD wMessage - The message to send
  1047.  * 
  1048.  * CUSTOMIZATION: You will only need to call CallBack once if there
  1049.  *                is only one LPOLECLIENT in your OBJ structure, which there
  1050.  *                should be.
  1051.  *
  1052.  */
  1053. void SendObjMsg (LPOBJ lpobj, WORD wMessage)
  1054. {
  1055.    int i;
  1056.    for (i=0; i < clpoleclient; i++)
  1057.    {
  1058.       if (lpobj->lpoleclient[i])
  1059.       {
  1060.          // Call the object's Callback function.
  1061.          lpobj->lpoleclient[i]->lpvtbl->CallBack 
  1062.             (lpobj->lpoleclient[i], wMessage, (LPOLEOBJECT) lpobj);
  1063.       }
  1064.       else
  1065.          break;
  1066.    }
  1067. }
  1068.  
  1069.  
  1070.  
  1071. /* SizeObj
  1072.  * -------
  1073.  *
  1074.  * Change the size of an object.
  1075.  *
  1076.  * HWND hwnd  - The object's window
  1077.  * RECT rect  - The requested new size in device units
  1078.  * BOOL fMove - Should the object be moved? (or just resized?)
  1079.  *
  1080.  * CUSTOMIZATION: Server Demo specific
  1081.  *
  1082.  */
  1083. void SizeObj (HWND hwnd, RECT rect, BOOL fMove)
  1084. {
  1085.    LPOBJ lpobj;
  1086.  
  1087.    lpobj = HwndToLpobj (hwnd);
  1088.    if (fMove)
  1089.    {
  1090.       lpobj->native.nX   = rect.left;
  1091.       lpobj->native.nY   = rect.top;
  1092.    }
  1093.    lpobj->native.nWidth  = rect.right  - rect.left;
  1094.    lpobj->native.nHeight = rect.bottom - rect.top ;
  1095.    SetHiMetricFields (lpobj);
  1096.    InvalidateRect (hwnd, (LPRECT)NULL, TRUE);
  1097.    fDocChanged = TRUE;
  1098.    if (docMain.doctype == doctypeFromFile)
  1099.    {
  1100.       // If object is linked, update it in client now. 
  1101.       SendObjMsg (lpobj, OLE_CHANGED);
  1102.    }
  1103. }
  1104.